
#include "CTData.h"

#include <wx/image.h>

#include <iostream>
#include <fstream>
#include <bitset>
#include <limits>


using namespace std;


CTData::CTData(const std::string &path)
:	SpatialData()
{
	loadData(path);
	bbox = BBox(Vec3(0.0, 0.0, 0.0), Vec3(xDim, yDim, zDim));
}


void CTData::getValueRange(float *min, float *max)
{
	*min = minValue;
	*max = maxValue;
}


float CTData::getValue(float x, float y, float z)
{
	//FIXME: Parece que essa função está retornando 0 quando (x, y, z) está no limite superior da bbox. Isso é adequado?

	x /= xDim;
	y /= yDim;
	z /= zDim;

	int i = x * xRes;
	int j = y * yRes;
	int k = z * zRes;

	if((i >= xRes || i < 0) || (j >= yRes || j < 0) || (k >= zRes || k < 0))
		return 0.0;
	else
		return data[i][j][k];
}

void CTData::loadData(const std::string &path)
{
	ifstream metaData_file((path + "/META").c_str());

	if(metaData_file)
	{
		// Resolução da grade tridimensional de voxels
		metaData_file >> xRes;
		metaData_file >> yRes;
		metaData_file >> zRes;

		// Dimensão da bounding box
		metaData_file >> xDim;
		metaData_file >> yDim;
		metaData_file >> zDim;

		metaData_file.close();
	}
	else
	{
		cout << "Não foi possível abrir o arquivo \"path/META\"" << endl;
	}


	data = new float**[xRes];

	for(int i = 0; i < xRes; i++){
		data[i] = new float*[yRes];

		for(int j = 0; j < yRes; j++){
			data[i][j] = new float[zRes];
		}
	}

	minValue = numeric_limits<float>::max();
	maxValue = numeric_limits<float>::min();

	for(int k = 0; k < zRes; k++)
	{
		//TODO: Generalizar a leitura para permitir qualquer nome de arquivo.
		wxString path_name(path.c_str(), wxConvUTF8);
		wxString file_name = wxString::Format(wxT("%s/data/%d"), path_name.GetData(), k+1);

		cout << "Lendo arquivo " << file_name.ToAscii()<< " ..." << endl;
		wxImage *img = new wxImage(file_name);

		for(int i = 0; i < xRes; i++)
		for(int j = 0; j < yRes; j++)
		{
			//Como as imagens são em gray scale, as componentes são iguais.
			float x = img->GetRed(i, j);
			data[i][j][k] = x;

			if(x < minValue)
				minValue = x;
			if(x > maxValue)
				maxValue = x;

			//cout << "Data = " << data[i][j][k] << endl;
		}

		delete img;
		cout << "Camada " << k << " lida de " << zRes << "." << endl;
	}
}
